函数式编程之记忆
是一种时间换空间的方法,用牺牲空间的复杂度来换取时间的复杂度
字符串连接
function f() {
var s = arguments.length + Array.prototype.join.call(arguments);
console.log(s);
};
这里使用的是Array.prototype.join方法进行字符串连接
返回的是连接的结果
接下来,写一个具有记忆的函数
// 这是一个用于返回f()的带有记忆功能的函数
function memorize(f) {
var cacho = {}; // 定义一个用于保存值的私有变量
return function() {
var key = arguments.length + Array.prototype.join.call(arguments, ',');
if (key in cacho)
return cacho[key];
else
return cacho[key] = f.call(this, arguments);
};
}
这是一个具有记忆的函数,用数组的长度和数组合并后组成的字符串作为属性名,进行保存,如果这个值存在则直接进行保存,如果值不存在则进行保存并返回(因为赋值语句会返回右值,所以return语句后无需再跟进行返回值的语句)
使用调试函数对其进行修改
// 这是一个用于返回f()的带有记忆功能的函数
function memorize(f) {
var cacho = {}; // 定义一个用于保存值的私有变量
console.log(cacho);
return function() {
var key = arguments.length + Array.prototype.join.call(arguments, ',');
console.log(key);
if (key in cacho) {
console.log(cacho[key]);
return cacho[key];
}
else {
console.log(f.call(this,arguments));
return cacho[key] = f.call(this, arguments);
};
};
}
这样就更加的明显了
使用这个函数
返回两个整数的最大公约数
欧几里得算法
由欧几里得最先发现,一个用于计算最大公因数的算法
function gcd(a, b) {
var t; // 用于保存中间变量
if(a < b) // 确保 a >= b
t = a, a = b, b = t;
while(t != 0)
t = a % b, a = b, b = t;
return a;
}
利用欧几里得算法写的求两个数的最大公因数,运行一下
gcd(85, 187);
17
计算结果正确,使用刚刚实现的具有记忆功能的高阶函数,将函数传进去,生成了一个新的函数
var functiongcd = memorize(gcd);
Object { }
使用这个函数
好吧。莫名进行死循环了。
Error: Script terminated by timeout at:
gcd@Scratchpad/1:35:9
memorize/<@Scratchpad/1:24:27
@debugger eval code:1:1
没办法继续排查错误
排查错误
// 这是一个用于返回f()的带有记忆功能的函数
function memorize(f) {
var cache = {};
console.log(cache);
return function() {
var key = arguments.length + Array.prototype.join.call(arguments);
console.log(key);
if (key in cache) {
console.log(cache[key]);
return cache[key];
}
else {
console.log(f.apply(this,arguments));
return cache[key] = f.apply(this, arguments);
};
};
}
这个函数依旧写错了,call只能传入一个值,而apply能传入多个值
继续运行
gcdmemo(85, 187);
285,187 Scratchpad/1:17:4
17 Scratchpad/1:23:7
17
其中第一个Scratchpad/1:17:4返回指代的是
if (key in cache) {
console.log(cache[key]);
return cache[key];
}
其中第二个Scratchpad/1:23:7返回指代的是
return cache[key] = f.apply(this, arguments);
好啦,非常明显,第一步是先将值缓存进入其私有变量,即保存进入闭包内部,然后第二个是发现这个值已经保存过了直接输出
(^o^)/,
js的记忆折腾完毕~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。